package org.hawk.gwt.ppc.introspection.impl;

import java.util.List;

import org.hawk.gwt.ppc.introspection.JavaConstructor;
import org.hawk.gwt.ppc.introspection.JavaField;
import org.hawk.gwt.ppc.introspection.JavaGenericTypeScope;
import org.hawk.gwt.ppc.introspection.JavaMethod;
import org.hawk.gwt.ppc.introspection.JavaModifier;
import org.hawk.gwt.ppc.introspection.JavaScope;
import org.hawk.gwt.ppc.introspection.JavaTypeScope;
import org.hawk.gwt.ppc.introspection.JavaTypeVariable;
import org.hawk.gwt.ppc.introspection.JavaVariable;
import org.hawk.gwt.ppc.parser.CompilationUnitDescriptor;
import org.hawk.gwt.ppc.parser.Descriptor;

/**
 * Common superclass for all generic types.
 * Generic types are independent from binary or source-based types
 * and provides own introspection implementation.
 * 
 * @author alex.bereznevatiy@gmail.com
 *
 */
abstract class AbstractJavaGenericTypeScope extends JavaScopeImpl implements
		JavaGenericTypeScope {
	
	private JavaTypeScope raw;
	private JavaScope owner;

	AbstractJavaGenericTypeScope(JavaTypeScope raw, JavaScope owner) {
		this.raw = raw;
		this.owner = owner;
		if (raw != null) {
			init(null, (JavaScopeImpl) raw.getParent());
		}
	}

	/*
	 * (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.JavaTypeScope#isInterface()
	 */
	public boolean isInterface() {
		return getRaw().isInterface();
	}

	/*
	 * (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.JavaTypeScope#isClass()
	 */
	public boolean isClass() {
		return getRaw().isClass();
	}

	/*
	 * (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.JavaTypeScope#isEnum()
	 */
	public boolean isEnum() {
		return getRaw().isEnum();
	}

	/*
	 * (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.JavaTypeScope#isAnnotation()
	 */
	public boolean isAnnotation() {
		return getRaw().isAnnotation();
	}

	/*
	 * (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.JavaTypeScope#getInterfaces()
	 */
	public List<JavaTypeScope> getInterfaces() {
		return getRaw().getInterfaces();
	}

	/*
	 * (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.JavaTypeScope#getSuperClass()
	 */
	public JavaTypeScope getSuperClass() {
		return getRaw().getSuperClass();
	}

	/*
	 * (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.JavaTypeScope#getName()
	 */
	public String getName() {
		return getRaw().getName();
	}

	/*
	 * (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.JavaTypeScope#getConstructors()
	 */
	public List<JavaConstructor> getConstructors() {
		return getRaw().getConstructors();
	}

	/*
	 * (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.JavaTypeScope#getMethods()
	 */
	public List<JavaMethod> getMethods() {
		return getRaw().getMethods();
	}

	/*
	 * (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.JavaTypeScope#getFields()
	 */
	public List<JavaField> getFields() {
		return getRaw().getFields();
	}

	/*
	 * (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.JavaTypeScope#getGenericSuperclass()
	 */
	public JavaTypeScope getGenericSuperclass() {
		return getRaw().getGenericSuperclass();
	}

	/*
	 * (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.JavaTypeScope#getGenericInterfaces()
	 */
	public List<JavaTypeScope> getGenericInterfaces() {
		return getRaw().getGenericInterfaces();
	}

	/*
	 * (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.JavaTypeScope#getDependingTypes()
	 */
	public List<String> getDependingTypes() {
		return getRaw().getDependingTypes();
	}

	/*
	 * (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.JavaTypeScope#getField(java.lang.String)
	 */
	public JavaField getField(String name) {
		return getRaw().getField(name);
	}

	/*
	 * (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.JavaTypeScope#getDeclaredClasses()
	 */
	public List<JavaTypeScope> getDeclaredClasses() {
		return getRaw().getDeclaredClasses();
	}

	/*
	 * (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.JavaTypeScope#isPrimitive()
	 */
	public boolean isPrimitive() {
		return false;
	}

	/*
	 * (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.JavaTypeScope#isPrimitiveWrapper()
	 */
	public boolean isPrimitiveWrapper() {
		return false;
	}

	/*
	 * (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.JavaParameterizable#getTypeVariables()
	 */
	public List<JavaTypeVariable> getTypeVariables() {
		return getRaw().getTypeVariables();
	}

	/*
	 * (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.JavaGenericTypeScope#getOwner()
	 */
	public JavaScope getOwner() {
		return owner;
	}

	/*
	 * (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.JavaGenericTypeScope#getRawType()
	 */
	public JavaTypeScope getRawType() {
		return getRaw();
	}

	/* (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.impl.JavaScopeImpl#getScope(int, int)
	 */
	@Override
	public JavaScope getScope(int line, int offset) {
		return getRaw().getScope(line, offset);
	}

	/* (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.impl.JavaScopeImpl#getVariable(java.lang.String, int, int)
	 */
	@Override
	public JavaVariable getVariable(String name, int line, int offset) {
		return getRaw().getVariable(name, line, offset);
	}

	/* (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.impl.JavaScopeImpl#getParent()
	 */
	@Override
	public JavaScope getParent() {
		return getRaw().getParent();
	}

	/* (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.impl.JavaScopeImpl#getChildren()
	 */
	@Override
	public List<JavaScope> getChildren() {
		return getRaw().getChildren();
	}

	/* (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.impl.JavaScopeImpl#getBestMatchMethod(java.lang.String, java.util.List)
	 */
	@Override
	public JavaMethod getBestMatchMethod(String name,
			List<JavaTypeScope> arguments) {
		return getRaw().getBestMatchMethod(name, arguments);
	}

	/* (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.impl.JavaScopeImpl#resolveType(java.lang.String, org.hawk.gwt.ppc.parser.CompilationUnitDescriptor)
	 */
	@Override
	JavaTypeScope resolveType(String name, CompilationUnitDescriptor context) {
		return ((JavaScopeImpl)owner).resolveType(name, context);
	}

	/* (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.impl.JavaScopeImpl#getCompilationUnit()
	 */
	@Override
	CompilationUnitDescriptor getCompilationUnit() {
		return ((JavaScopeImpl)owner).getCompilationUnit();
	}

	/* (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.impl.JavaScopeImpl#getDescriptor()
	 */
	@Override
	Descriptor getDescriptor() {
		return ((JavaScopeImpl)getRaw()).getDescriptor();
	}

	/* (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.impl.JavaScopeImpl#resolveTypeParameter(java.lang.String)
	 */
	@Override
	JavaTypeVariable resolveTypeParameter(String paramName) {
		return ((JavaScopeImpl)getRaw()).resolveTypeParameter(paramName);
	}

	/* (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.impl.AbstractJavaStatement#getModifiers()
	 */
	@Override
	public List<JavaModifier> getModifiers() {
		return ((JavaScopeImpl)getRaw()).getModifiers();
	}

	/* (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.JavaTypeScope#isAssignableFrom(org.hawk.gwt.ppc.introspection.JavaTypeScope)
	 */
	public boolean isAssignableFrom(JavaTypeScope from) {
		if (from instanceof JavaGenericTypeScope) {
			from = ((JavaGenericTypeScope)from).getRawType();
		}
		return getRaw().isAssignableFrom(from);
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object obj) {
		if (obj == null) {
			return false;
		}
		if (obj == this) {
			return true;
		}
		JavaTypeScope raw;
		if (obj instanceof JavaGenericTypeScope) {
			raw = ((JavaGenericTypeScope)obj).getRawType();
		} else if (obj instanceof JavaTypeScope) {
			raw = (JavaGenericTypeScope)obj;
		} else {
			return false;
		}
		return getRaw().equals(raw);
	}

	JavaTypeScope getRaw() {
		return raw;
	}
}
